// (C) Copyright 2012 Beijing Kystar. All rights reserved.

`timescale 1ns/100ps
`default_nettype none

module vin_io 
#(parameter
    MAX_VIN_WIDTH = 0
)
(
    input  wire          I_sclk,
    input  wire          I_rst_n,

    input  wire          I_vin_pclk,
    input  wire          I_vin_vsync,
    input  wire          I_vin_de,
    input  wire [ 23: 0] I_vin_data,

    output wire          O_vin_pclk,
    output reg           O_vin_vsync,
    output reg           O_vin_de,
    output reg  [ 23: 0] O_vin_data,

    input  wire [ 11: 0] I_reg_px_start_row_offset,
    input  wire [ 11: 0] I_reg_px_start_col_offset,
    input  wire [ 11: 0] I_reg_vin_max_width,
    input  wire [ 11: 0] I_reg_vin_max_height,

    output wire [ 12: 0] O_reg_rb_vin_width,
    output wire [ 12: 0] O_reg_rb_vin_height,
    output wire [  7: 0] O_reg_rb_vin_frame_rate,
    output wire          O_reg_rb_video_not_active,

    output wire          O_vin_led

);

/******************************************************************************
                                <localparams>
******************************************************************************/

/******************************************************************************
                              <internal signals>
******************************************************************************/
wire pclk;
reg  [ 15: 0] vsync_dly;
reg  de_io;
reg  [ 23: 0] data_io;
reg  de_dly0;
reg  [ 23: 0] data_dly0;
reg  de_dly1;
reg  [ 23: 0] data_dly1;
reg  de_dly2;
reg  [ 23: 0] data_dly2;
reg  de_dly3;
reg  [ 23: 0] data_dly3;
reg  [ 10: 0] de_cnt;
reg  vin_vsync_dly;
reg  [ 6: 0] dvi_vsync_cnt;
wire vin_de;
wire [ 23: 0] vin_data;
wire de_filter;
wire [ 23: 0] data_filter;

/******************************************************************************
                                <module body>
******************************************************************************/
assign pclk = I_vin_pclk;
//BUFG u_bufg_vin_pclk(
//    .I(I_vin_pclk),
//    .O(pclk)
//);

assign O_vin_pclk = pclk;

always @(posedge pclk)
    begin
    vsync_dly <= {vsync_dly[14:0], I_vin_vsync};
    if (vsync_dly == 'd0)
        O_vin_vsync <= 1'b0;
    else if (vsync_dly == 16'hFFFF)
        O_vin_vsync <= 1'b1;
    vin_vsync_dly <= O_vin_vsync;
    end

always @(posedge pclk)
    begin
    de_io <= I_vin_de;
    data_io <= I_vin_data;
    de_dly0 <= de_io;
    data_dly0 <= data_io;
    de_dly1 <= de_dly0;
    data_dly1 <= data_dly0;
    end

vin_fmt_detect
#(
    .MAX_IN_WIDTH(MAX_VIN_WIDTH),
    .MAX_IN_HEIGHT(4095),
    .IN_WIDTH_BW(13),
    .IN_HEIGHT_BW(13)
)
u_vin_fmt_detect
(
    .I_video_pclk(pclk),
    .I_video_vsync(vin_vsync_dly),
    .I_video_de(de_dly1),
    .I_sclk(I_sclk),
    .I_rst_n(I_rst_n),
    .O_video_start(),
    .O_video_over(),
    .O_video_width(O_reg_rb_vin_width),
    .O_video_height(O_reg_rb_vin_height),
    .O_video_frame_rate(O_reg_rb_vin_frame_rate),
    .O_video_not_active(O_reg_rb_video_not_active)
);

vin_de_filter u_vin_de_filter
(
    .I_pclk(pclk),
    .I_de(de_dly1),
    .I_data(data_dly1),
    .O_de(de_filter),
    .O_data(data_filter),
    .I_vin_width(O_reg_rb_vin_width)
);

vin_crop u_vin_crop(
    .I_pclk(pclk),
    .I_new_frame(!vin_vsync_dly && O_vin_vsync),
    .I_de(de_filter),
    .I_data(data_filter),
    .O_de(vin_de),
    .O_data(vin_data),
    .I_reg_row_offset(I_reg_px_start_row_offset),
    .I_reg_col_offset(I_reg_px_start_col_offset),
    .I_reg_vin_max_width(I_reg_vin_max_width),
    .I_reg_vin_max_height(I_reg_vin_max_height)

);

always @(posedge pclk or negedge I_rst_n)
    if (!I_rst_n)
        begin
        O_vin_de <= 1'b0;
        O_vin_data <= 'd0;
        end
    else
        begin
        O_vin_de <= vin_de;
        O_vin_data <= vin_data;
        end

always @(posedge pclk)
    begin
    if (O_vin_vsync && !vin_vsync_dly)
        dvi_vsync_cnt <= dvi_vsync_cnt + 1;
    end

assign O_vin_led = dvi_vsync_cnt[6];

endmodule
`default_nettype wire

